
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Accessible TabView</title>

<style type="text/css">
/*margin and padding on body element
  can introduce errors in determining
  element position and are not recommended;
  we turn them off as a foundation for YUI
  CSS treatments. */
body {
	margin:0;
	padding:0;
}
</style>

<link type="text/css" rel="stylesheet" href="../../build/cssfonts/fonts-min.css" />
<script type="text/javascript" src="../../build/yui/yui-min.js"></script>


<!--begin custom header content for this example-->
<style type="text/css">

	/*	The following style rules necessary to override style rules in the 
		YUI CSS file. */

	#example ul,
	#example li {
		list-style: none;
		list-style: none;		
	}
	
	#example em {
		font-style: normal;
	}

	#example .yui-tabpanel {

		/*	Use the "zoom" property to set the the hasLayout property to true.
			This ensures that the background color of the tab's panel will 
			be rendered correctly when the example is running in the 
			example chrome.
		*/

		_zoom: 1;

	}

	#example .yui-tabpanel a {
		text-decoration: underline;
		color: blue;
	}
	
	#example h3 {
		color: #000;
		font-size: 100%;
		font-weight: bold;
	}

	#example .yui-tabview {
		margin: 0 .25em;
	}
	

	/*	Hide the instructional text used to label the tabview offscreen.
	 	This ensures it is still available to users of screen readers, but is 
		not visible to sighted users.	*/

	#tabview-heading em {
		position: absolute;
		left: -999em;
	}


	/*	Hide the list while it is being transformed into a tabview.	*/

	.yui-loading #tabview-1 {
		display: none;
	}

</style>
<script type="text/javascript">

	//	Add a class to the documentElement to prevent the user from seeing 
	//	the unstyled menu while the necessary CSS and JavaScript 
	//	dependancies are being fetched.

	document.documentElement.className = "yui-loading";

</script>
<!--end custom header content for this example-->

</head>

<body class=" yui-skin-sam">

<h1>Accessible TabView</h1>

<div class="exampleIntro">
	<p>
This example illustrates how to create an accessible tabview widget using the 
Focus Manager Node Plugin, 
<a href="../../api/YUI.html#event_delegate">Event's delegation support</a>, and 
Node's support for the 
<a href="http://www.w3.org/TR/wai-aria/">WAI-ARIA Roles and States</a>.
</p>			
</div>

<!--BEGIN SOURCE CODE FOR EXAMPLE =============================== -->

<h3 id="tabview-heading">Today's News</h3>
<div id="tabview-1" class="yui-tabview">
    <ul>
        <li class="yui-tab yui-tab-selected"><a href="#top-stories"><em>Top Stories</em></a></li>
        <li class="yui-tab"><a href="#world-news"><em>World</em></a></li>
        <li class="yui-tab"><a href="#entertainment-news"><em>Entertainment</em></a></li>
        <li class="yui-tab"><a href="#sports-news"><em>Sports</em></a></li>
        <li class="yui-tab"><a href="#technology-news"><em>Technology</em></a></li>		
    </ul>            
    <div>
        <div class="yui-tabpanel yui-tabpanel-selected" id="top-stories">
			<h3>Top Stories</h3>
				        	
        </div>
        <div class="yui-tabpanel" id="world-news">
			<h3>World News</h3>
			        </div>
        <div class="yui-tabpanel" id="entertainment-news">
			<h3>Entertainment News</h3>
				        	
        </div>
        <div class="yui-tabpanel" id="sports-news">
			<h3>Sports News</h3>
				        	
        </div>
        <div class="yui-tabpanel" id="technology-news">
			<h3>Technology News</h3>
				        	
        </div>			
    </div>
</div>

<!-- YUI Seed -->
<script type="text/javascript" src="../../build/yui/yui.js"></script>
<script type="text/javascript">

	YUI({ 

			base: "../../build/",
			modules: {
				"tabview-css": {
					type: "css",
					fullpath: "assets/tabview.css"
				}    
			},
			timeout: 10000

		}).use("tabview-css", "node-focusmanager", "node-event-simulate", function(Y) {
		

		var tabView = Y.Node.get("#tabview-1"),
			tabList = tabView.query("ul"),
			tabHeading = Y.Node.get("#tabview-heading"),
			sInstructionalText = tabHeading.get("innerHTML");
			selectedTabAnchor = tabView.query(".yui-tab-selected>a"),
			bGeckoIEWin = ((Y.UA.gecko || Y.UA.ie) && navigator.userAgent.indexOf("Windows") > -1),
			panelMap = {};


		//	Remove the "yui-loading" class from the documentElement
		//	now that the necessary YUI dependencies are loaded.

		tabView.get("ownerDocument").get("documentElement").removeClass("yui-loading");


		//	Apply the ARIA roles, states and properties.

		//	Add some instructional text to the heading that will be read by
		//	the screen reader when the first tab in the tabview is focused.

		tabHeading.set("innerHTML", (sInstructionalText + " <em>Press the enter key to load the content of each tab.</em>"));
		tabList.set("aria-labelledby", "tabview-heading");

		tabList.set("role", "tablist");
		tabView.query("div").set("role", "presentation");


		tabView.plug(Y.Plugin.NodeFocusManager, { 
				descendants: ".yui-tab>a",
				keys: { next: "down:39", //	Right arrow
						previous: "down:37" },	// Left arrow
				focusClass: {
					className: "yui-tab-focus",
					fn: function (node) {
						return node.get("parentNode");
					}
				},
				circular: true
			});


		//	If the list of tabs loses focus, set the activeDescendant 
		//	attribute to the currently selected tab.

		tabView.focusManager.after("focusedChange", function (event) {

			if (!event.newVal) {	//	The list of tabs has lost focus
				this.set("activeDescendant", selectedTabAnchor);
			}

		});


		tabView.queryAll(".yui-tab>a").each(function (anchor) {

			var sHref = anchor.getAttribute("href", 2),
				sPanelID = sHref.substring(1, sHref.length),
				panel;

			//	Apply the ARIA roles, states and properties to each tab
			
			anchor.set("role", "tab");
			anchor.get("parentNode").set("role", "presentation");


			//	Remove the "href" attribute from the anchor element to  
			//	prevent JAWS and NVDA from reading the value of the "href"
			//	attribute when the anchor is focused

			if (bGeckoIEWin) {
				anchor.removeAttribute("href");
			}

			//	Cache a reference to id of the tab's corresponding panel
			//	element so that it can be made visible when the tab
			//	is clicked.
			panelMap[anchor.get("id")] = sPanelID;
			

			//	Apply the ARIA roles, states and properties to each panel

			panel = Y.Node.get(("#" + sPanelID));

			panel.setAttrs({
				role: "tabpanel",
				"aria-labelledby": anchor.get("id")
			});

		});


		//	Use the "delegate" custom event to listen for the "click" event
		//	of each tab's <A> element.

		Y.on("delegate", function (event) {

			var selectedPanel,
				oTarget = event.currentTarget,
				sID = oTarget.get("id");

			//	Deselect the currently selected tab and hide its 
			//	corresponding panel.

			if (selectedTabAnchor) {
				selectedTabAnchor.get("parentNode").removeClass("yui-tab-selected");
				Y.Node.get(("#" + panelMap[selectedTabAnchor.get("id")])).removeClass("yui-tabpanel-selected");
			}
			
			selectedTabAnchor = oTarget;
			selectedTabAnchor.get("parentNode").addClass("yui-tab-selected");
			
			selectedPanel = Y.Node.get(("#" + panelMap[sID]));
			selectedPanel.addClass("yui-tabpanel-selected");
			
			creatingPaging(selectedPanel);
			
			//	Prevent the browser from following the URL specified by the 
			//	anchor's "href" attribute when clicked.
			
			event.preventDefault();

		}, tabView, "click", ".yui-tab>a");


		//	Since the anchor's "href" attribute has been removed, the 
		//	element will not fire the click event in Firefox when the 
		//	user presses the enter key.  To fix this, dispatch the 
		//	"click" event to the anchor when the user presses the 
		//	enter key.
		
		if (bGeckoIEWin) {

			Y.on("delegate", function (event) {

				if (event.charCode === 13) {
					event.currentTarget.simulate("click");
				}

			}, "#tabview-1", "keydown", ">ul>li>a");

		}
		
		
		var creatingPaging = function (panel) {

			var listitem,
				sHTML,
				paging;

			if (!panel.query(".paging")) {

				listitem = selectedTabAnchor.get("parentNode");
				sHTML = "";
			
				if (listitem.previous()) {
					sHTML += '<button type="button" class="yui-tabview-prevbtn">Previous Tab Panel</button>';
				}
			
				if (listitem.next()) {
					sHTML += '<button type="button" class="yui-tabview-nextbtn">Next Tab Panel</button>';
				}

				paging = Y.Node.create('<div class="paging">' + sHTML + '</div>');
			
				panel.appendChild(paging);
			
			}
			
		};

		creatingPaging(Y.Node.get(".yui-tabpanel-selected"));


		Y.on("delegate", function (event) {

			var node = selectedTabAnchor.get("parentNode").previous().query("a");

			tabView.focusManager.focus(node);
			node.simulate("click");

		}, tabView, "click", ".yui-tabview-prevbtn");
		

		Y.on("delegate", function (event) {

			var node = selectedTabAnchor.get("parentNode").next().query("a");

			tabView.focusManager.focus(node);
			node.simulate("click");

		}, tabView, "click", ".yui-tabview-nextbtn");			

	});

</script>

<!--END SOURCE CODE FOR EXAMPLE =============================== -->

</body>
</html>
